/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package adirector;

import com.neurotechnology.NMatcher.NMatcher;
import pkg1ifxArchivos.cifxConfig;
import pkg1ifxArchivos.cifxLogs;

/**
 *
 * @author gabriel
 */
public class saSpeedMatch {

    //Variables con templates
    int nregistrosporhilo=2000; //Numero de registros que seran asignados a cada hilo de busqueda
    int nnumhilos=10;//Numero de hilos para ejecucion de busquedas del tipo saThradSpeedMacth
    private saOspeedMatch[] speedTTemplates = new saOspeedMatch[0];
    private static cifxLogs olog=null;// = new cifxLogs("appbots.log");
    private static cifxConfig oconf=null ;//= new cifxConfig("appbots.conf",olog);
    //private NMatcher matcher=null;
    //Para los resultados
    private Record[] rresultado;
    private String srespuesta="";
    private int ntipo=0; //0=HUELLA;1=ROSTRO;2=IRIS

    private boolean b_clasico=false;
    private boolean turbo=false;
    public void setTurbo(boolean dato)
    {
        turbo=dato;
    }
    public boolean getTurbo()
    {
        return turbo;
    }
    int nMatchingTreshold=90;
    //Para manejo de macher local en proceso
    boolean bmlocal=true;
    public saSpeedMatch(NMatcher mdato,cifxConfig cdato,cifxLogs ldato,int tipo)
    {
        try
        {
            //matcher=mdato;
            olog=ldato;
            oconf=cdato;
            ntipo=tipo;
            if(oconf==null)
            {
                oconf=new cifxConfig("appbots.conf",olog);
            }
            if(ntipo==0)
            {
                if(oconf.traeParametro("B_CLASICO").contains("SI"))
                    b_clasico=true;
                nregistrosporhilo=Integer.valueOf(oconf.traeParametro("REG_POR_HILO_H"));
                nnumhilos=Integer.valueOf(oconf.traeParametro("NUM_HILOS_H"));
                nMatchingTreshold=Integer.valueOf(oconf.traeParametro("MATCHINGTRESHOLD"));
                if(oconf.traeParametro("ACTIVAR_TURBO").equals("SI"))
                    turbo=true;
                if(turbo)
                    olog.outMensaje("TURBO ACTIVADO!!!!");
                olog.outMensaje("saSpeedMatch.saSpeedMatch(): NUM REGISTROS POR HILO (HUELLA): "+nregistrosporhilo);
                olog.outMensaje("saSpeedMatch.saSpeedMatch(): NUM HILOS (HUELLA): "+nnumhilos);
            }
            else
            {
                if(oconf.traeParametro("B_CLASICO").contains("SI"))
                    b_clasico=true;
                nregistrosporhilo=Integer.valueOf(oconf.traeParametro("REG_POR_HILO_R"));
                nnumhilos=Integer.valueOf(oconf.traeParametro("NUM_HILOS_R"));
                nMatchingTreshold=Integer.valueOf(oconf.traeParametro("MATCHINGTRESHOLD"));
                if(oconf.traeParametro("ACTIVAR_TURBO").equals("SI"))
                    turbo=true;

                if(turbo)
                    olog.outMensaje("TURBO ACTIVADO!!!!");

                olog.outMensaje("saSpeedMatch.saSpeedMatch(): NUM REGISTROS POR HILO(ROSTRO): "+nregistrosporhilo);
                olog.outMensaje("saSpeedMatch.saSpeedMatch(): NUM HILOS: (ROSTRO)"+nnumhilos);

            }
            
            //saOspeedMatch ststmp=new saOspeedMatch(matcher, olog,turbo,nMatchingTreshold,bmlocal);
            saOspeedMatch ststmp=new saOspeedMatch(olog,turbo,nMatchingTreshold);

            agregaThreadSpeedMatch(ststmp);
        }catch(Exception e)
        {
            olog.outMensaje("saSpeedMatch.saSpeedMatch(): ERROR(1) : "+e.getMessage());
        }
    }

    public Record[] getResultados()
    {
       return rresultado;
    }
    public String getRespuesta()
    {
        return srespuesta;
    }
    public String find(byte[] dato)
    {
        //b_clasico=false;
        if(b_clasico)
            return findClasic(dato);
        else
           return findNemo(dato);
        //Prueba2
        //return findNemo(dato);
        //Original
        //return findClasic(dato);
    }
    public synchronized String findClasic(byte[] dato)//Retorna los resultados
    {
        try
        {
            olog.outMensaje("<---saSpeedMatch.find(): INICIO BUSQUEDA DEL TEMPLATE : "+dato.toString());
            srespuesta="";
            //int nrespuestas=0;
            int nrespOK=0;
            int ncuantosfueron=speedTTemplates.length;
            saThrdSpeedMatch[] eltrhread = new saThrdSpeedMatch[ncuantosfueron];
            for(int i=0;i<ncuantosfueron;i++)
            {
                //saThrdSpeedMatch eltrhread = new saThrdSpeedMatch(speedTTemplates[i]);
                eltrhread[i] = new saThrdSpeedMatch(speedTTemplates[i]);
                speedTTemplates[i].setResultado(new Record[0]);
                speedTTemplates[i].setNumResOK(0);
                speedTTemplates[i].setDocResultados("");
                speedTTemplates[i].setTemplate(dato);
                eltrhread[i].start();

                //speedTTemplates[i].setTemplate(dato);
                //speedTTemplates[i].start();
            }

            String stmp="";
            int nthreadsmuertos=0;

            //while(true)
            do
            {
                for(int t=0;t<eltrhread.length;t++)
                {
                   if(!eltrhread[t].isAlive() && !eltrhread[t].getYaEntro())
                    {
                        //if(speedTTemplates[t].getEstado()!=-9)
                        //{
                        stmp=speedTTemplates[t].getDocResultados();
                        if(!stmp.equals(""))
                        {
                            srespuesta=srespuesta+stmp;
                            nrespOK+=speedTTemplates[t].getNumRespOK();
                        }

                        //nrespuestas++;
                        eltrhread[t].setYaEntro(true);

                        //}
                        nthreadsmuertos++;
                    }
                }

                //if(nrespuestas>=speedTTemplates.length)
                //    break;
            }while(nthreadsmuertos<ncuantosfueron);

            if(nrespOK>0)
                srespuesta=nrespOK+srespuesta;
            olog.outMensaje("<---saSpeedMatch.find(): TERMINA BUSQUEDA DEL TEMPLATE RESPUESTA: "+srespuesta);
            return srespuesta;
        }catch(Exception e)
        {
            olog.outMensaje("saSpeedMatch.findClasic(): ERROR(0) : "+e.getMessage());
            olog.outMensaje("saSpeedMatch.findClasic(): ERROR(0) : "+e.toString());
            return "";
        }
    }
    //Strail 23feb2012 Buscando a nemo

    private synchronized  int buscandoANemo(int inicio, int fin)//Retorna el indice de la respuesta
    {

        try{
            for(int t=inicio;t<fin;t++)
            {

                if(!eltrhread2[t].getYaEntro()){

                    if(!eltrhread2[t].isAlive())
                    {
                        //olog.outMensaje("saSpeedMatch.buscandoANemo(): HILO["+t+"]RESPUESTA: "+speedTTemplates[t].getDocResultados

                        //if(!eltrhread2[t].getYaEntro())
                        //{



                            //if(speedTTemplates[t].getDocResultados().length()>0)
                            if(eltrhread2[t].getSaOspeedMatch().getEstado()!=-9)
                            {
                                eltrhread2[t].setYaEntro(true);
                                nmuertos++;
                                
                                if(eltrhread2[t].getSaOspeedMatch().getEstado()==202)
                                {
                                    olog.outMensaje("saSpeedMatch.buscandoANemo(): MRT HILO["+t+"]RESPUESTA: "+eltrhread2[t].getSaOspeedMatch().getDocResultados());
                                    return t;

                                }
                            }
                        //}

                    }
                }
            }
        } catch (Exception e)
        {
           olog.outMensaje("saSpeedMatch.findNemo(): ERROR(0) : "+e.getMessage());
        }
        return -1;
    }

    private saThrdSpeedMatch[] dameUnArreglo(saThrdSpeedMatch[] src,int inicio, int tamano)
    {
        saThrdSpeedMatch[] strdTMP=new saThrdSpeedMatch[tamano];
        System.arraycopy(src, inicio, strdTMP, 0, tamano);
        return strdTMP;
    }
    //Find Con Buscando a nemo

    private int nmuertos=0;
    private int ncuantosfueron2=0;
    private saThrdSpeedMatch[] eltrhread2 =null;
    public synchronized String findNemo(byte[] dato)//Retorna los resultados
    {
        try
        {
            olog.outMensaje("<---saSpeedMatch.findNemo(): INICIO BUSQUEDA DEL TEMPLATE : "+dato.toString());

            srespuesta="";
            //int nrespuestas=0;
            int nrespOK=0;

            ncuantosfueron2=0;
            eltrhread2=null;
            ncuantosfueron2=speedTTemplates.length;
            eltrhread2 = new saThrdSpeedMatch[ncuantosfueron2];
            
            for(int i=0;i<ncuantosfueron2;i++)
            {
                //saThrdSpeedMatch eltrhread = new saThrdSpeedMatch(speedTTemplates[i]);
                eltrhread2[i] = new saThrdSpeedMatch(speedTTemplates[i]);
                eltrhread2[i].getSaOspeedMatch().setResultado(new Record[0]);
                eltrhread2[i].getSaOspeedMatch().setNumResOK(0);
                eltrhread2[i].getSaOspeedMatch().setEstado(-9);
                eltrhread2[i].getSaOspeedMatch().setDocResultados("");
                eltrhread2[i].getSaOspeedMatch().Salir=false;
                eltrhread2[i].getSaOspeedMatch().setTemplate(dato);
                eltrhread2[i].start();

                //speedTTemplates[i].setTemplate(dato);
                //speedTTemplates[i].start();
            }

            //while(true)
            int tmn1=eltrhread2.length/3;
            int ncual=-1;
            nmuertos=0;
            do
            {

                if((ncual=buscandoANemo(0,tmn1))>=0)
                {
                    srespuesta=srespuesta+speedTTemplates[ncual].getDocResultados();
                    nrespOK+=speedTTemplates[ncual].getNumRespOK();
                    if(nrespOK>0)
                        break;
                }
                if((ncual=buscandoANemo(tmn1,tmn1*2))>=0)
                {
                    srespuesta=srespuesta+speedTTemplates[ncual].getDocResultados();
                    nrespOK+=speedTTemplates[ncual].getNumRespOK();
                    if(nrespOK>0)
                        break;
                }
                if((ncual=buscandoANemo(tmn1*2,eltrhread2.length))>=0)
                {
                    srespuesta=srespuesta+speedTTemplates[ncual].getDocResultados();
                    nrespOK+=speedTTemplates[ncual].getNumRespOK();
                    if(nrespOK>0)
                        break;
                }

                //if(nrespuestas>=speedTTemplates.length)
                //    break;
            }while(nmuertos<ncuantosfueron2);

            if(nrespOK>0)
                srespuesta=nrespOK+srespuesta;
            olog.outMensaje("<---saSpeedMatch.findNemo(): TERMINA BUSQUEDA DEL TEMPLATE RESPUESTA: "+srespuesta);
            for(int i=0;i<eltrhread2.length;i++)
            {
                    eltrhread2[i].getSaOspeedMatch().Salir=true;
                    //eltrhread2[i]=null;
            }

            return srespuesta;
        }catch(Exception e)
        {
            olog.outMensaje("saSpeedMatch.findNemo(): ERROR(0) : "+e.getMessage());
            olog.outMensaje("saSpeedMatch.findNemo(): ERROR(0) : "+e.toString());
            return "";
        }
    }
    public int buscaTemplates() //Retorna -1 ERROR, 0 No existe, 1 Existe
    {
        try{

            
            return 1;
        }catch(Exception e)
        {
            olog.outMensaje("saSpeedMatch.buscaTemplates(): ERROR : "+e.getMessage());
            return -1;
        }

    }
    public void setThreadSpeedMatch(saOspeedMatch[] dato)
    {
        speedTTemplates=dato;
    }
    public saOspeedMatch[] getThreadSpeedMatch()
    {
        return speedTTemplates;
    }
    int posArreglo=0;
    int posRegArreglo=0;
    private void agregaThreadSpeedMatch(saOspeedMatch dato)
    {
        try{

            saOspeedMatch[] rtmp= new saOspeedMatch[speedTTemplates.length];
            System.arraycopy(speedTTemplates, 0, rtmp, 0, speedTTemplates.length);
            speedTTemplates = new saOspeedMatch[speedTTemplates.length+1];
            System.arraycopy(rtmp, 0, speedTTemplates, 0, rtmp.length);
            speedTTemplates[speedTTemplates.length-1]=dato;

        }catch(Exception e)
        {
            olog.outMensaje("saSpeedMatch.agregaThreadSpeedMatch(): ERROR : "+e.getMessage());
        }

    }
    public void agregaRecordTemplate(Record dato)
    {
        try
        {
            
            if(speedTTemplates.length <nnumhilos || nnumhilos==-1)
            {
                if(speedTTemplates[speedTTemplates.length-1].getRecords().length<nregistrosporhilo)
                {
                    speedTTemplates[speedTTemplates.length-1].agregaRecord(dato);
                }
                else
                {
                    //System.gc();
                    //saOspeedMatch ststmp=new saOspeedMatch(matcher, olog,turbo,nMatchingTreshold,bmlocal);
                    saOspeedMatch ststmp=new saOspeedMatch(olog,turbo,nMatchingTreshold);
                    agregaThreadSpeedMatch(ststmp);
                    speedTTemplates[speedTTemplates.length-1].agregaRecord(dato);
                }
            }
           /* speedTTemplates[speedTTemplates.length-1].agregaRecord(dato);
            if(speedTTemplates[speedTTemplates.length-1].getRecords().length==nregistrosporhilo)
            {
                
                if(nnumhilos<speedTTemplates.length || nnumhilos==-1)
                {
                    saOspeedMatch ststmp=new saOspeedMatch(matcher, olog,turbo);
                    agregaThreadSpeedMatch(ststmp);
                }
            }
            *
            */

        }catch(Exception e)
        {
            olog.outMensaje("saSpeedMatch.agregaRecordTemplate(): ERROR : "+e.getMessage());
        }


    }


}
